#include "keys.h"

/* carega vetores na memoria */
int cria_vetor(pNo_PK *obras, char arquivo[], int tamstr, int *tamanho) {

		char *titulo, *indice;
		FILE *nrr;
		long lSize;
		int i;

		nrr = fopen(arquivo, "rb");
		if(nrr) {
		fseek (nrr, 0 ,SEEK_END); /* Nrr existe! procura o seu tamanho total */
		lSize = ftell(nrr); 
		rewind (nrr); /*volta para o inicio */
		titulo = (char*) malloc (sizeof(char)*(tamstr+1));
		indice = (char*) malloc (sizeof(char)*(dig_nrr+1));
		for(i=1;i<=lSize/(tamstr+dig_nrr);i++) {   /* faz a insercao dos dados do arquivos com o loop */
			fread (titulo,1,(tamstr),nrr);
			fseek (nrr, ((tamstr+dig_nrr)*i-dig_nrr) ,SEEK_SET); /* recebe o titulo e o indice da obra */
			fread (indice,1,dig_nrr,nrr);
				titulo[tamstr] = '\0';
				indice[dig_nrr] = '\0';
			*tamanho = Le_PK(&(*obras),titulo,atoi(indice),*tamanho, tamstr); /* adiciona um por um no vetor "obras" */
			fseek (nrr, ((tamstr+dig_nrr)*i) ,SEEK_SET); /* espera no comeco do proximo titulo */
		}
		qsort (*obras, *tamanho, sizeof (No_PK), compara); /* ordena o vetor */
		fclose(nrr);
		free(titulo);
		free(indice);
	return 1;
}
else return 0;
}

int PKposition(FILE *pk, int pos, char string[], int *indice) {

int avpos=0;
				avpos = insere(pk, pos, tam_titulo);
				if(avpos != 0) {
					fseek(pk, (avpos-1)*(tam_titulo+dig_nrr),SEEK_SET);
					}
				else {
					fclose(pk);
					pk = fopen(string,"a+");
					avpos = *indice;
					}
return avpos;

}

/* pega o indice (nrr) do ultimo inserido no arquivo de indice secundario */
int indice(char string[]) {
	FILE *pk;
	int indice;
	long lSize;
	pk = fopen (string,"rb");
	if(pk) {
		fseek (pk, 0 ,SEEK_END); /* vai ate o final e pega o tamanho total */
		lSize = ftell(pk);
		indice = (lSize/(tam_titulo+dig_nrr)+1);
	fclose(pk);
	return indice;
}
	else return 0;
}

int main() {
	pNo_PK obras, sk_titulo, sk_autor, sk_tipo, sk_ano;
	int n=0, tamanho=0, tautor = 0, ttitulo = 0, ttipo = 0, tano=0, ititulo = 1;
	FILE *base, *avail, *pk_titulo, *pk_tipo, *pk_autor, *pk_ano;
	int nrr_base=0, i=1, j=1;
	char *tit;
	/* roda a funcao para atualizar os arquivos de acordo com o base00.dat */
	int b = 0, atual = 0; 
	int iautor = 1 , itipo = 1, iano = 1;
	char * buffer, titulo_aux[tam_titulo+1];
	size_t result;
	long lSize;
	int ERRO = 1;
	int itituloaux=1, itipoaux=1, iautoraux=1, ianoaux=1;
	/* alocacao dos 5 vetores com espaco inicial para 20 registros */

	obras = malloc((sizeof(No_PK)*20)); 
	sk_titulo = malloc((sizeof(No_PK)*20)); 
	sk_tipo = malloc((sizeof(No_PK)*20)); 
	sk_autor = malloc((sizeof(No_PK)*20)); 
	sk_ano = malloc((sizeof(No_PK)*20)); 
	base = fopen ("base00.dat","rb");				
	

		
	if(cria_vetor(&obras, "nrr.dat", tam_titulo, &tamanho) &&
	cria_vetor(&sk_titulo, "sk_titulo.dat", tam_titulo, &ttitulo) &&
	cria_vetor(&sk_tipo, "sk_tipo.dat", tam_tipo, &ttipo) &&
	cria_vetor(&sk_autor,"sk_autor.dat", tam_autor, &tautor) &&
	cria_vetor(&sk_ano, "sk_ano.dat", tam_ano, &tano))
		{ /* alguns arquivos nao sao carregados na memoria, por isso sao abertos so para verificar sua existencia */
		i = tamanho+2;
		ititulo = indice("pk_titulo.dat");
		itipo = indice("pk_tipo.dat");
		iautor = indice("pk_autor.dat");
		iano = indice("pk_ano.dat");
	if(ititulo && itipo && iautor && iano)
		ERRO = 0;
	b=tamanho;
		}		
	

else if (ERRO) { /* caso algum deles nao exista, vai reler todos da base (os arquivos provavelmente estarao conflitantes ou corrompidos) */

	if(base) { 							/* base existe */
		fseek (base, 0 ,SEEK_END);
		lSize = ftell (base);  /*calcula o tamanho total da base */
		rewind (base);			
		buffer = malloc (sizeof(char)*(tam_titulo+1)); 
		
		/* criacao do vetor que sera gravado no disco como nrr.dat posteriormente. Vetor de indices primarios */
		
		for(i=1;i<=lSize/tam_total;i++) { 
			result = fread (buffer,1,(tam_titulo),base);	/* recebe o titulo e o indice da obra */
			tamanho = Le_PK(&obras,buffer,i,tamanho,tam_titulo);
			qsort (obras, tamanho, sizeof (No_PK), compara);
			fseek (base, (tam_total*i) ,SEEK_SET); 
		}
		
		/* criacao dos arquivos vazios de pk para cada categoria */

		pk_titulo = fopen ("pk_titulo.dat","w");
		pk_tipo = fopen("pk_tipo.dat","w");
		pk_autor = fopen ("pk_autor.dat","w");
		pk_ano = fopen("pk_ano.dat","w");

		/* criacao dos 4 sks (na memoria) em conjunto com os seus respectivos arquivos de pks */ 
		
		for(j=1;j<=lSize/tam_total;j++) { 
			fseek(base, atual, SEEK_SET);
			fread (titulo_aux,1,(tam_titulo),base);
			 
			/* caso o quinto caractere de titulo lido da base seja diferente de * (se tiver * quer dizer que foi removido e por isso nao deve ser adicionado nas nossas chaves) ele fara a adicao desse registro */

			if(titulo_aux[4] != '*') {
				atual = Secondary(&sk_titulo, base, pk_titulo , tam_titulo, &ititulo, atual, &ttitulo, b); 
				atual = Secondary(&sk_tipo, base, pk_tipo , tam_tipo, &itipo, atual, &ttipo, b);
				atual = Secondary(&sk_autor, base, pk_autor , tam_autor, &iautor, atual, &tautor, b);
				atual = Secondary(&sk_ano, base, pk_ano, tam_ano, &iano, atual, &tano, b); 
				fseek (base, (tam_total*j) ,SEEK_SET);
			}
			b++;
			atual = tam_total*j;
		}
		/* fecha todos os arquivos abertos */

		free(buffer);
		fclose(pk_titulo);
		fclose(pk_tipo);
		fclose(pk_autor);
		fclose(pk_ano);
	}
}
if(!base) { 
	base = fopen("base00.dat", "w"); /* cria os arquivos caso a base nao exista */
	pk_titulo = fopen("pk_titulo.dat", "w");
	pk_ano = fopen("pk_ano.dat", "w");
	pk_autor = fopen("pk_autor.dat", "w");
	pk_tipo = fopen("pk_tipo.dat", "w");

	fclose(pk_titulo);
	fclose(pk_tipo);
	fclose(pk_autor);
	fclose(pk_ano);
}

fclose(base);

	tit = malloc(sizeof(char)*(tam_titulo+1));
	while (n != 4) {  /* inicio da interface com o usuario, mantem loop enquanto n diferente de 3 */  
		printf("**********************************************\n**********************************************\n**                                          **\n         1 - Adicionar novo titulo\n         2 - Realizar consultas\n         3 - Remover titulo\n         4 - Sair\n**                                          **\n**********************************************\n**********************************************\n");
		scanf("%d", &n);
		__fpurge(stdin);
		switch(n) {
			case 1:
				if(!(avail = fopen ( "avail_head.dat" , "rb" ))){ /* checa se avail_list ja existe, caso nao existe, ele cria com valor -001 */
					cria_avail ();	}
				else fclose(avail);
				base = fopen("base00.dat", "r+");
				nrr_base = insere(base, pos_base, tam_total); /* recebe nrr na qual a base será inserido */
				if(nrr_base != 0) {/* caso nrr seja diferente de zero vai para a posicao */
					nrr_base--;
					atual = (nrr_base) * tam_total;
					fseek(base, atual, SEEK_SET);

					Titulo(obras,tit,base,tamanho); /* adiciona um novo titulo */ 
					Tipo(base);
					Autor(base);
					Ano(base);
					Valor(base);
					Imagem(base);
					printf("\nAdicionado a Base de Dados!\n\n");
					fclose(base); /* fecha base */
					tamanho = Le_PK(&obras,tit,(nrr_base+1),tamanho, tam_titulo); /* adiciona esse novo titulo e seu nrr (o proximo i) na 	memoria */
					qsort (obras, tamanho, sizeof (No_PK), compara);
				}
				else { /* caso nrr seja 0, adiciona no fim */

				itituloaux = ititulo; /* da primeira vez apenas deixa os auxiliares com o valor final */
				itipoaux = itipo; /* da segunda em diante atualiza seus valores */
				iautoraux = iautor; /* caso nao entre no else, o valor final do indice ainda sera o mesmo */
				ianoaux = iano; /* por isso nao precisara de atualizacao */

					fclose(base);
					base = fopen ("base00.dat", "a+");
				
				Titulo(obras,tit,base,tamanho); /* adiciona um novo titulo */ 
				Tipo(base);
				Autor(base);
				Ano(base);
				Valor(base);
				Imagem(base);
				printf("\nAdicionado a Base de Dados!\n\n");
				fclose(base); /* fecha base */
				tamanho = Le_PK(&obras,tit,(b+1),tamanho, tam_titulo); /* adiciona esse novo titulo e seu nrr (o proximo i) na memoria */
				qsort (obras, tamanho, sizeof (No_PK), compara);
				i++;
				nrr_base=b;  /* atualiza o indicador de nrr */
				}
				base = fopen ("base00.dat","rb"); /* reabre base com outro parametro */

				pk_titulo = fopen ("pk_titulo.dat","r+");
				pk_tipo = fopen("pk_tipo.dat","r+");
				pk_autor = fopen ("pk_autor.dat","r+");
				pk_ano = fopen("pk_ano.dat","r+");


				ititulo =PKposition(pk_titulo, pos_titulo, "pk_titulo.dat", &itituloaux);
				itipo = PKposition(pk_tipo, pos_tipo, "pk_tipo.dat", &itipoaux);
				iautor = PKposition(pk_autor, pos_autor, "pk_autor.dat", &iautoraux);
				iano = PKposition(pk_ano, pos_ano, "pk_ano.dat", &ianoaux);


				atual=nrr_base*tam_total;
				fseek (base, atual ,SEEK_SET);
				fread (titulo_aux,1,(tam_titulo),base);




				atual = Secondary(&sk_titulo, base, pk_titulo , tam_titulo, &ititulo, atual, &ttitulo, nrr_base);
				atual = Secondary(&sk_tipo, base, pk_tipo , tam_tipo, &itipo, atual, &ttipo, nrr_base);
				atual = Secondary(&sk_autor, base, pk_autor , tam_autor, &iautor, atual, &tautor, nrr_base);
				atual = Secondary(&sk_ano, base, pk_ano , tam_ano, &iano, atual, &tano, nrr_base);

				b++;

				fclose(base);
				fclose(pk_titulo);
				fclose(pk_tipo);
				fclose(pk_autor);
				fclose(pk_ano);

				break;
			case 2:
				menu_consulta(obras, tamanho, sk_titulo, sk_tipo, sk_autor, sk_ano, ttitulo, ttipo, tautor, tano, tamanho); /* entra na secao de consulta */
				break;
			case 3:
				if(!(avail = fopen ( "avail_head.dat" , "rb" ))) /* checa se avail_list ja existe, caso nao existe, ele cria com valor -001 */
					cria_avail ();
				else fclose(avail);
				remocao(&obras, &sk_titulo, &sk_tipo, &sk_autor, &sk_ano, &tamanho, ttitulo, ttipo, tautor, tano);
			case 4:
				break;
			default:
				printf("Opcao invalida\n");
				break;	
		}
	}
	if ((base=fopen("base00.dat", "rb"))) {

	/* se a base existe a gravacao dos vetores de obras e sks precisam ser gravados em disco */ 
	
	GravaArray("nrr.dat", tamanho, obras); 
	GravaArray("sk_titulo.dat", ttitulo, sk_titulo);
	GravaArray("sk_tipo.dat", ttipo, sk_tipo);
	GravaArray("sk_autor.dat", tautor, sk_autor);
	GravaArray("sk_ano.dat", tano, sk_ano); 
	fclose(base);
	}

	/*libera os vetores */
	free(tit);
	free(obras); 
	free(sk_titulo);
	free(sk_tipo);
	free(sk_autor);
	free(sk_ano);
	printf("Encerrando programa.\n"); 
	return 0;	
}

